package ResultsManager;

##########################
#     OmnibusProxy       #
#    Krzysztof Ulman     #
# Politechnika Krakowska #
#      Kraków 2012       #
##########################

use strict;
use warnings;
use encoding 'utf8';

use AppConfig;
use Database;
use ResultObject;
use SearcherDto;
use StatementDto;

#handler do bazy
our $db;

#konstruktor
sub new {
	shift;
	my $self = {};
	bless $self;
	
	if(!$db) {
		$db = Database->new();
	}
	
	return $self;
}

sub setStatementDto {
	my $self = shift;
	my $statementDto = shift;
	$self->{statementDto} = $statementDto;
}

sub setSearcherDto {
	my $self = shift;
	my $searcherDto = shift;
	$self->{searcherDto} = $searcherDto;
}

#zapisuje wyniki do bazy danych
sub saveResults {
	my $self = shift;
	my $resultListRef = shift;
	my @resultList = @{$resultListRef};
	my $statementDto = $self->{statementDto};
	my $searcherDto = $self->{searcherDto};
	my $MAX_RESULTS_PER_STATEMENT = AppConfig->getProperty('MAX_RESULTS_PER_STATEMENT');
	
	Screen->printAndLogDebug('Zapisuje liste wynikow z wyszukiwarki ' . $searcherDto->getName() 
								. ', sztuk dostepnych ' . scalar(@resultList) 
								. ', zapis pierwszych ' . $MAX_RESULTS_PER_STATEMENT);
	my $searcherId = $searcherDto->getSearcherId();
	my %justAddedUrls;
	my $resultNum = 0;
	foreach my $resultDto (@resultList) {
		#zabezpieczamy przed dwukrotnym wpisaniem tego samego linku dla jednej frazy
		if(!$justAddedUrls{$resultDto->getUrl()}) {
			my $urlId = private_getUrlId($self, $resultDto, $statementDto);
			$db->insertResult($resultDto, $urlId, $searcherId, 1);
			$justAddedUrls{$resultDto->getUrl()} = 1;
			$resultNum++;
		}

		#zapisujemy tylko tyle ile potrzeba i ani jednego wiecej
		if($resultNum >= $MAX_RESULTS_PER_STATEMENT) {
			last;
		}
	}
#	foreach my $resultDto (@resultList) {
#		my $shouldUpdate = 1;
#		if($justAddedUrls{$resultDto->getUrl()}) {
#			$shouldUpdate = 0;
#		}
#		my $urlId = private_getUrlId($self, $resultDto, $statementDto);
#		$db->insertResult($resultDto, $urlId, $searcherId, $shouldUpdate);
#		$justAddedUrls{$resultDto->getUrl()} = 1;
#		
#		#zapisujemy tylko tyle ile potrzeba i ani jednego wiecej
#		$resultNum++;
#		if($resultNum >= $MAX_RESULTS_PER_STATEMENT) {
#			last;
#		}
#	}
}

#identyfikator rekordu z tabeli urls
sub private_getUrlId {
	my $self = shift;
	my $resultDto = shift;
	my $statementDto = shift;
	
	#szukamy konkretnego adresu w bazie
	my $urlAddrId = private_selectUrlAddrId($resultDto->getUrl());
	if(!$urlAddrId) {
		#jezeli nie znaleziono to dodajemy nowy
		$urlAddrId = $db->insertUrlAddr($resultDto->getUrl(), $resultDto->getTitle());
		if(!$urlAddrId) {
			#jezeli nadal puste to cos nie tak
			die('Nie udalo sie wstawic do bazy adresu: ' . $resultDto->getUrl());
		}
	}
	
	#szukamy konkretnego obiektu URL w bazie
	my $urlId = $db->selectUrlId($statementDto->getStatementId(), $urlAddrId);
	if(!$urlId) {
		#jezeli nie ma to wstawiamy nowy
		$urlId = $db->insertUrl($statementDto->getStatementId(), $urlAddrId);
		if(!$urlId) {
			#jezeli nadal puste to cos nie tak
			die('Nie udalo sie powiazac ' . $statementDto->getStatement . ' z URL o id ' . $urlId);
		}
	}
	
	return $urlId;	
}

sub private_selectUrlAddrId {
	my $url = shift;
	my $id = $db->selectUrlAddrId($url);
	if(!$id) {
		my $isWithWwwInDb = 0;
		my $tmpUrl;
		#jezeli pusty to probujemy szukac z/bez 'www'
		if($url =~ /^www./) {
			$tmpUrl = substr($url, 4, length($url));
		} else {
			$isWithWwwInDb = 1;
			$tmpUrl = 'www.' . $url;
		}
		$id = $db->selectUrlAddrId($tmpUrl);
		if($id && $isWithWwwInDb) {
			#zmieniamy w bazie adres na taki bez www, bo po co to trzymac ;)
			$db->updateUrlAddr($id, $url);
		}
	}
	return $id;
}

#obliczenie wskaznika globalnego
sub computeGlobalRank {
	my $self = shift;
	my $spiderNumConst = shift;
	my $statementDto = $self->{statementDto};
	my $MAX_RESULTS_PER_STATEMENT = AppConfig->getProperty('MAX_RESULTS_PER_STATEMENT');
	
	Screen->printAndLogDebug('Obliczam globalna pozycje dla frazy {' . $statementDto->getStatement() . '}');
	
	#pobranie URLi dla frazy
	my $urlRef = $db->selectUrlsByStatementId($statementDto->getStatementId());
	my @urls = @{$urlRef};
	foreach my $urlId (@urls) {
		my $positionsRef = $db->selectPositionsByUrlId($urlId);
		my @positions = @{$positionsRef};
		my $spidersNum = $spiderNumConst;
		my $sum = 0;
		
		#sumujemy wagi pobrane z bazy
		foreach my $position (@positions) {
			$sum += $position;
			$spidersNum--;
		}
		
		#dodajemy wagi dla linkow, ktore nie zostaly znalezione we wszystkich wyszukiwarkach
		while($spidersNum > 0) {
			#skoro zbiaramy N pozycji, to nieistniejący link przyjmujemy, ze ma pozycje N+1
			$sum += ($MAX_RESULTS_PER_STATEMENT + 1);
			$spidersNum--;
		}
		
		#srednia arytmetyczna pozycji
		my $globalRank = $sum / $spiderNumConst;
		
		#zapis do bazy
		$db->updateGlobalRankByUrlId($urlId, $globalRank);
	}
}

#zapisuje blad do bazy danych
sub storeErrorMessage {
	my $self = shift;
	my $message = shift;
	my $statementDto = $self->{statementDto};
	$db->storeErrorMessage($message, $statementDto->getStatementId());
}

1;